package com.lh.process.engine.model;

import com.lh.process.engine.instance.ProcessorInstanceCreator;
import com.lh.process.engine.node.ProcessorDefinition;
import com.lh.process.engine.node.ProcessorNode;
import com.lh.process.engine.process.Processor;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

/**
 * @author: linghao
 * @since: 2022/10/18
 */
@Data
public class ProcessModel {

    private String name;
    private Map<String,ProcessNodeModel> nodes = new HashMap<>();

    public void add(ProcessNodeModel nodeModel){
        if(nodes.containsKey(nodeModel.getName())){
            throw new IllegalArgumentException("同一个流程中不能包含相同的name节点");
        }
        nodes.put(nodeModel.getName(),nodeModel);
    }

    public void check() {
        int beginNode = 0;
        for(ProcessNodeModel processNodeModel : nodes.values()){
            String className = processNodeModel.getClassName();
            try {
                Class.forName(className);  //检查node class是否能正常加载
            }catch (Exception e){
                throw new IllegalArgumentException("不能加载"+processNodeModel.getName()+"节点的class："+processNodeModel.getClassName());
            }

            String nextNode = processNodeModel.getNextNode();
            if(nextNode != null){
                String[] splitNode = nextNode.split(",");
                for(String name : splitNode){
                    if(!nodes.containsKey(name)){
                        throw new IllegalArgumentException("节点[name=]"+name+"不存在");
                    }
                }
            }
            if(processNodeModel.getBegin()){
                beginNode++;
            }
        }
        if(beginNode!=1){
            throw new IllegalArgumentException("不合法的流程，每个流程只能有一个开始节点");
        }
    }

    public ProcessorDefinition build(ProcessorInstanceCreator instanceCreator) throws Exception {
        Map<String, ProcessorNode> processorNodeMap = new HashMap<>();
        ProcessorDefinition processorDefinition = new ProcessorDefinition();
        processorDefinition.setName(this.name);
        //初始化所有ProcessorNode
        for(ProcessNodeModel processNodeModel : nodes.values()){
            Processor processor = instanceCreator.newInstance(processNodeModel.getClassName(), processNodeModel.getName());
            ProcessorNode processorNode = new ProcessorNode();
            processorNode.setName(processNodeModel.getName());
            processorNode.setProcessor(processor);
            processorNode.setInvokeMethod(processNodeModel.getInvokeMethod());
            if(processNodeModel.getBegin()){
                processorDefinition.setFirst(processorNode);
            }
            processorNodeMap.put(processNodeModel.getName(),processorNode);
        }
        //关联每个节点ProcessorNode中的nextNodes
        for(ProcessorNode processorNode : processorNodeMap.values()){
            String nextNode = nodes.get(processorNode.getName()).getNextNode();
            if(nextNode == null){
                continue;
            }
            String[] split = nextNode.split(",");
            for(String node : split){
                processorNode.addNextNode(processorNodeMap.get(node));
            }
        }

        return processorDefinition;
    }
}
